package org.imfuture.pocketzk.core.dao.hibernate;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.imfuture.pocketzk.core.dao.GenericDao;
import org.imfuture.pocketzk.core.model.BaseObject;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * Created on: 2007/10/26
 *
 * @author Alan She(scw1109)
 */
public abstract class GenericDaoHibernate<E extends BaseObject> implements GenericDao<E> {

    private Class<E> persistentClass;

    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    public GenericDaoHibernate() {
        this.persistentClass = (Class<E>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    public Class<E> getPersistentClass() {
        return persistentClass;
    }

    @SuppressWarnings("unchecked")
    public E findById(Long id, boolean lock) {
        E entity;
        if (lock)
            entity = (E) getCurrentSession().load(getPersistentClass(), id, LockMode.UPGRADE);
        else
            entity = (E) getCurrentSession().load(getPersistentClass(), id);

        return entity;
    }

    @SuppressWarnings("unchecked")
    public List<E> findAll() {
        return findByCriteria();
    }

    @SuppressWarnings("unchecked")
    public E makePersistent(E entity) {
        getCurrentSession().saveOrUpdate(entity);
        return entity;
    }

    public void makeTransient(E entity) {
        getCurrentSession().delete(entity);
    }

    public void flush() {
        getCurrentSession().flush();
    }

    public void clear() {
        getCurrentSession().clear();
    }

    @SuppressWarnings("unchecked")
    protected List<E> findByCriteria(Criterion... criterion) {
        Criteria crit = getCurrentSession().createCriteria(getPersistentClass());
        for (Criterion c : criterion) {
            crit.add(c);
        }
        return crit.list();
    }
}
